/*
 * Copyright 2010 Thedwick, LLC

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

     http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

 */
package com.thedwick.jdbcGrabber;

import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.Properties;

import com.thedwick.jdbcGrabber.sink.SQLSink;
import com.thedwick.jdbcGrabber.util.ClassUtil;

public class gbDriver implements Driver {
	private Properties testingConfig;
	static {
		try {
			System.out.println("Registering jdbcGrabber driver");
			DriverManager.registerDriver(new gbDriver());
			
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	/**
	 * Used by JDBC
	 */
	public gbDriver(){
		
	}
	
	/**
	 * Used only for testing.  Allows injection of properties instead of 
	 * finding them from the classpath
	 * @param properties
	 */
	public gbDriver(Properties properties) {
		this.testingConfig = properties;
	}

	@Override
	public boolean acceptsURL(String url) throws SQLException {
		log("testing " + url);
		return url.indexOf("jdbcGrabber") > -1;
	}

	@Override
	public Connection connect(String url, Properties info) throws SQLException {
		if (acceptsURL(url)){
			try {
				Properties config = createConfig(url);
				Connection underlying = createUnderlying(config, info);
				SQLSink sink = createSink(config);
				return new gbConnection(sink, underlying);
			} catch (IOException e){
				throw new SQLException(e);
			} 
		} else {
			return null;
		} 
	}

	private void log(String string) {
		System.out.println(string);
		DriverManager.println(string);
	}
	
	private SQLSink createSink(Properties config) {
		return (SQLSink) ClassUtil.createInstance("sink.class", config, config);
	}

	private Connection createUnderlying(Properties config, Properties info) throws SQLException {
		String url = config.getProperty("url");
		Driver driver = (Driver) ClassUtil.createInstance("driver", config, new Object[0]);
		Connection conn = driver.connect(url, info);
		return conn;
	}

	private Properties createConfig(String url) throws IOException {
		if (this.testingConfig != null){
			return this.testingConfig;
		}
		
		int fileStart = url.indexOf("config=") + 7;
		int fileEnd = url.indexOf(".properties",fileStart);
		String fileName = url.substring(fileStart,fileEnd) + ".properties";
		InputStream file = getClass().getResourceAsStream(fileName);
		if (file == null){
			throw new IOException("File not found in class path: " + fileName);
		}
		Properties rv = new Properties();
		rv.load(file);
		return rv;
	}

	@Override
	public int getMajorVersion() {
		return 0;
	}

	@Override
	public int getMinorVersion() {
		return 1;
	}

	@Override
	public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
			throws SQLException {
		return new DriverPropertyInfo[0];
	}

	@Override
	public boolean jdbcCompliant() {
		return true;
	}

}
